package com.block.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.channelext.service.IActionInfoService;
import com.block.common.config.AliIPConfig;
import com.block.common.constant.RedisKeyConstant;
import com.block.common.model.vo.ReqIpInfoVO;
import com.block.common.service.IChannelCommonService;
import com.block.common.service.ICountCommonService;
import com.block.common.service.IMemberCommonService;
import com.block.common.service.IProductCommonService;
import com.block.common.util.ALiIpUtil;
import com.block.common.util.LocalDateUtil;
import com.block.db.common.vo.BaseUserInfoVo;
import com.block.db.entity.ChannelInfo;
import com.block.db.entity.MemberExtInfo;
import com.block.db.entity.ProductInfo;
import com.block.db.entity.ProductPush;
import com.block.db.mapper.MemberExtInfoMapper;
import com.block.db.mapper.ProductInfoMapper;
import com.block.product.enums.ProdPriceTypeEnum;
import com.block.product.enums.ProductTypeEnum;
import com.block.product.model.dto.ProdUnionDTO;
import com.block.product.model.vo.ProductInfoVO;
import com.block.product.service.IProductInfoService;
import com.block.product.service.IProductMemberUnionService;
import com.block.product.service.IProductProfitService;
import com.block.product.service.IProductPushService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.swing.plaf.metal.MetalMenuBarUI;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品信息（下游/甲方） 服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-29
 */
@Service
public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, ProductInfo> implements IProductInfoService {

    @Autowired
    IProductPushService productPushService;
    @Autowired
    IProductMemberUnionService productMemberUnionService;
    @Autowired
    IProductProfitService productProfitService;
    @Autowired
    ICountCommonService countCommonService;
    @Autowired
    AliIPConfig aliIPConfig;
    @Autowired
    IActionInfoService actionInfoService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    IChannelCommonService channelCommonService;
    @Autowired
    IProductCommonService productCommonService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    IMemberCommonService memberCommonService;
    @Resource
    MemberExtInfoMapper memberExtInfoMapper;

    /**
     * 查询产品信息
     * @return
     */
    @Override
    public List<ProductInfoVO> getProductInfoList( String clientType, Integer sceneId, BaseUserInfoVo userInfoVo, String userAgent) {

        // 获取满足条件的产品ID（根据上架信息查询的满足条件的产品信息）
        List<ProductPush> productPushList = productPushService.getProductIdList(clientType, sceneId, userInfoVo.getReChannelType());

        // 根据城市信息过滤掉不显示的产品信息
//        productPushList = filterProductInfoByNotShowCity(productPushList, userInfoVo.getIp(), userInfoVo.getReChannelCode());

        productPushList = filterProductInfoByZhimaFilter(productPushList, userInfoVo);

        productPushList = filterProductInfoByBrowser(productPushList, userAgent);

        // 获取可以展示的产品ID信息
        List<Long> productIdList = productPushList.stream().map(productPush -> productPush.getProductId()).collect(Collectors.toList());

        //根据渠道信息的不显示的产品信息，过滤不需要展示的产品信息
        productIdList = filterProductInfoByChannelCode(userInfoVo.getReChannelCode(), productIdList);
        if (CollUtil.isEmpty(productIdList)){
            return new ArrayList<>();
        }

        String nowDate = LocalDate.now().toString();
        List<ProductInfoVO> resultList = new ArrayList<>();
        for (Long productId: productIdList){

            String redisKey = StrUtil.format(RedisKeyConstant.PRODUCT_DAY_UV_COUNT_KEY, nowDate, productId);
            String productUvNumber = stringRedisTemplate.opsForValue().get(redisKey);
            if (ObjectUtil.isNotEmpty(productUvNumber) && Integer.valueOf(productUvNumber) < 0){
                // 今日剩余uv 为0
                continue;
            }

            ProductInfo productInfo = productCommonService.getProductInfoCache(String.valueOf(productId));

            // 根据是否为联登产品，进行产品信息的获取或者，缓存信息的展示
            ProductInfoVO infoVO = handleProductInfo(productInfo, userInfoVo);
            if (ObjectUtil.isNotEmpty(infoVO)){
                // 联登产品会产生没有撞库成功的情况
                resultList.add(infoVO);
            }
        }

        // 产品信息的统计
        if (ObjectUtil.equal(sceneId, Integer.valueOf(3))){
            // 统计产品列表的uv数据（ip 去重）
            String channelCode = userInfoVo.getReChannelCode();
            if (Arrays.asList("ios_card", "android_card").contains(userInfoVo.getReChannelCode())){
                // 已经不可用的渠道，可能会产生一些 uv统计数据
                channelCode = userInfoVo.getChannelCode();
            }
//            String channelCode = userInfoVo.getReChannelCode();
            String reqIp = userInfoVo.getIp();
            Long remainSecond = LocalDateUtil.getRemainSecondNumber();
            String redisKey = StrUtil.format(RedisKeyConstant.COUNT_UV_PROD_LIST_KEY, channelCode, reqIp);
            boolean result = stringRedisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis()+"", remainSecond, TimeUnit.SECONDS);
            if (result){
                // 加锁不成功，则直接返回
                countCommonService.countProdListUvNumber(channelCode, userInfoVo.getIp());
            }
        }

        return resultList;
    }

    /**
     * 浏览器过滤
     * @param productPushList
     * @param userAgent
     * @return
     */
    private List<ProductPush> filterProductInfoByBrowser(List<ProductPush> productPushList, String userAgent) {

       try {

           if (StrUtil.isEmpty(userAgent)){
               return productPushList;
           }
           UserAgent userAgentEntity = UserAgentUtil.parse(userAgent);

           List<ProductPush> resultList = new ArrayList<>();
           for (ProductPush productPush: productPushList){

               String notExcludeBrowser = productPush.getNotExcludeBrowser();
               if (StrUtil.isEmpty(notExcludeBrowser)){
                   resultList.add(productPush);
                   continue;
               }

               List<String> browserList = JSON.parseArray(notExcludeBrowser, String.class);
               if (CollUtil.isEmpty(browserList)){
                   resultList.add(productPush);
                   continue;
               }
               String name = userAgentEntity.getBrowser().getName();
               if (!browserList.contains(name)){
                   resultList.add(productPush);
               }
           }
           return resultList;
       }catch (Exception exception){
           exception.printStackTrace();
       }
        return productPushList;
    }


    private List<ProductPush> filterProductInfoByZhimaFilter(List<ProductPush> productPushList, BaseUserInfoVo userInfoVo) {

        List<ProductPush> resultList = new ArrayList<>();
        try {
            // 查询到用户ip信息
            for (ProductPush productPush: productPushList){

                String zhimaFilter = productPush.getZhimaFilter();
                // 芝麻过滤为空，产品显示
                if (StrUtil.isEmpty(zhimaFilter)){
                    resultList.add(productPush);
                    continue;
                }

                List<String> zhimaFilterList = JSON.parseArray(zhimaFilter, String.class);
                // 芝麻过滤为空，产品显示
                if (CollUtil.isEmpty(zhimaFilterList)){
                    resultList.add(productPush);
                    continue;
                }

                String zhima = userInfoVo.getZhima();
                if (StrUtil.isNotEmpty(zhima) && zhimaFilter.contains(zhima)){
                    // 芝麻过滤不为空，且用户芝麻在过滤范围内
                    resultList.add(productPush);
                }
            }
            return resultList;
        }catch (Exception exception){
            exception.printStackTrace();
        }
        return productPushList;
    }

    /**
     * 组装产品返回信息
     * @param productInfo
     * @param userInfoVo
     * @return
     */
    public ProductInfoVO handleProductInfo(ProductInfo productInfo, BaseUserInfoVo userInfoVo) {

        ProductInfoVO infoVO = new ProductInfoVO();

        infoVO.setProductId(String.valueOf(productInfo.getId()));
        infoVO.setProductName(productInfo.getProductName());
        infoVO.setLogoUrl(productInfo.getLogoUrl());
        infoVO.setItRate(productInfo.getInterestRate());
        infoVO.setTypeStr(ProductTypeEnum.getLabelByValue(productInfo.getType()));
        infoVO.setApplyNumber(String.valueOf(productInfo.getApplyNumber()));
        infoVO.setDescInfo(productInfo.getDescInfo());
        String loanAmount = String.format("%s-%s", productInfo.getMinLoanAmount(), productInfo.getMaxLoanAmount());
        infoVO.setLnAmount(loanAmount);
        String loanPeriod = String.format("%s-%s", productInfo.getMinLoanPeriod(), productInfo.getMaxLoanPeriod());
        infoVO.setLnPeriod(loanPeriod);
        infoVO.setProductLabel(productInfo.getProductLabel());

        infoVO.setUnionFlag(ObjectUtil.equal(productInfo.getPriceType(), ProdPriceTypeEnum.UNION.getValue())?1:0);
        if (ObjectUtil.equal(productInfo.getPriceType(), ProdPriceTypeEnum.UNION.getValue())){
            //
            if (ObjectUtil.equals(userInfoVo.getUserType(), Integer.valueOf(3))){
                // 暴力登陆的用户不进行联登
                return null;
            }

            // 查询用户联登产品的信息
            ProdUnionDTO prodUnionDTO = productMemberUnionService.findProductUnionMatchResult(productInfo, userInfoVo);
            if (prodUnionDTO.isShowFlag()){
                // 展示查询的联登产品的信息
                infoVO.setDetailUrl(StrUtil.isNotEmpty(prodUnionDTO.getProdUrl())?prodUnionDTO.getProdUrl():"");
            }else{
                // 不展示该联登产品信息
                return null;
            }
        }else{
            infoVO.setDetailUrl(productInfo.getDetailUrl());
        }
        return infoVO;
    }

    /**
     * 根据 不现实的城市信息 过滤掉产品信息
     * @param productPushList
     * @param reqIp
     * @return
     */
    public List<ProductPush> filterProductInfoByNotShowCity(List<ProductPush> productPushList, String reqIp, String reqChannelCode){

        List<ProductPush> resultList = new ArrayList<>();
        try {

            // 查询到用户ip信息
            ReqIpInfoVO reqIpAreaInfo = null;
            for (ProductPush productPush: productPushList){

                String notShowCitysStr = productPush.getNotShowCitys();
                if (StrUtil.isEmpty(notShowCitysStr)){
                    resultList.add(productPush);
                    continue;
                }

                List<String> codeList = JSON.parseArray(notShowCitysStr, String.class);
                // 城市过滤信息为空，产品显示
                if (CollUtil.isEmpty(codeList)){
                    resultList.add(productPush);
                    continue;
                }

                if (ObjectUtil.isEmpty(reqIpAreaInfo)){
                    reqIpAreaInfo = ALiIpUtil.getReqIpAreaInfo(reqIp, aliIPConfig.getAppCode());
                }

                if (!(codeList.contains(reqIpAreaInfo.getCityCode())
                        || codeList.contains(reqIpAreaInfo.getProvinceCode()))){
                    // 城市不在过滤的范围内，不过滤
                    resultList.add(productPush);
                }
            }
            return resultList;
        }catch (Exception exception){
            exception.printStackTrace();
        }
        return productPushList;
    }


    /**
     * 根据渠道信息的不显示的产品信息，过滤不需要展示的产品信息
     *
     * @param channelCode
     * @param productIdList
     * @return
     */
    public List<Long> filterProductInfoByChannelCode(String channelCode, List<Long> productIdList){
        try {
            ChannelInfo channelInfo = channelCommonService.getChannelInfoCache(channelCode);
            if (ObjectUtil.isEmpty(channelInfo) || StrUtil.isEmpty(channelInfo.getNotIncludeProduct())){
                return productIdList;
            }

            String ids = channelInfo.getNotIncludeProduct();
            JSONArray jsonArray = JSON.parseArray(ids);
            if (jsonArray.size() >= 0){
                for (int index = 0; index < jsonArray.size(); index++){
                    String idStr = jsonArray.getString(index);
                    if (productIdList.contains(Long.valueOf(idStr))){
                        // 产品列表中包含了，渠道信息不显示的产品ID
                        // 需要排除该产品信息
                        productIdList.remove(Long.valueOf(idStr));
                    }
                }
            }
            return productIdList;
        }catch (Exception exception){
            log.error(StrUtil.format("【过滤渠道不包含的产品信息】处理异常【channelCode】{}【productIdList】{}", channelCode, productIdList), exception);
        }
        return productIdList;
    }
}
